package cn.sangyy.basic.service.impl;

import cn.sangyy.basic.common.code.CodeEnum;
import cn.sangyy.basic.constent.BaseConstants;
import cn.sangyy.basic.dto.CodeInfoDto;
import cn.sangyy.basic.exception.BusinessException;
import cn.sangyy.basic.exception.CarAssert;
import cn.sangyy.basic.service.ICodeVerifyService;
import cn.sangyy.basic.utils.SmsUtils;
import cn.sangyy.basic.utils.StrUtils;
import cn.sangyy.basic.utils.VerifyCodeUtils;
import cn.sangyy.user.domain.LoginInfo;
import cn.sangyy.user.mapper.LoginInfoMapper;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author SangYY
 * @date: 2023/06/01/15:09
 */
@Service
public class CodeVerifyServiceImpl implements ICodeVerifyService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private LoginInfoMapper loginInfoMapper;

    @Override
    public String getBase64Str(String key) {
        //生成随机数验证码
        String code = StrUtils.getRandomString(4);
        //放到redis缓存里
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        String base64 = null;
        try {
            base64 = VerifyCodeUtils.VerifyCode(130, 42, code);
        } catch (IOException e) {
            e.printStackTrace();
            throw new BusinessException(e);
        }
        return base64;
    }

    @Override
    public void sendSmsCode(CodeInfoDto codeInfoDto) {
        //jsr303参数校验
        //图片验证码校验
        String imageCode = codeInfoDto.getImageCode();
        String imageCodeKey = codeInfoDto.getImageCodeKey();
        String mobile = codeInfoDto.getMobile();
        Object imageCodeRedis = redisTemplate.opsForValue().get(imageCodeKey);
        CarAssert.assertNotNull(imageCodeRedis,CodeEnum.REGISTER_IMAGE_CODE_KEY_NO_EXISTS);
        //比对图片验证码
        CarAssert.assertStrNotBlank(imageCode,CodeEnum.REGISTER_IMAGE_CODE_ERROR);
        if(!imageCode.equalsIgnoreCase(imageCodeRedis.toString())){
            throw new BusinessException(CodeEnum.REGISTER_IMAGE_CODE_ERROR);
        }
        String phoneKeyInRedis = BaseConstants.REGISTER_PHONE_CODE_IN_REDIS+ mobile;
        sendSms(mobile,phoneKeyInRedis);
    }

    private void sendSms(String mobile,String key) {
        String phoneCode = (String) redisTemplate.opsForValue().get(key);
        //验证码存在
        if(StringUtils.isNotBlank(phoneCode)){
            //判断是否过重新获取验证码的时间
            Long expireTime = redisTemplate.getExpire(key);
            if(expireTime != null && expireTime != -1 && expireTime != -2){
                if(expireTime - 60*1000 > 4*60*1000){ //没到重发时间，抛个异常
                    throw new BusinessException(CodeEnum.REGISTER_PHONE_NO_GET_CODE);
                }
            }else {
                throw new BusinessException("网络异常！");
            }
        }else {//验证码不存在
            phoneCode = VerifyCodeUtils.generateVerifyCode(6, "0123456789");
        }
        //设置到redis中去
        redisTemplate.opsForValue().set(key,phoneCode,5,TimeUnit.MINUTES);
        //阿里云短信服务发送短信验证码
        SmsUtils.sendSms(mobile,phoneCode);
        System.out.println("短信验证码："+phoneCode);
    }

    @Override
    public void sendSmsCodeToLogin(String phone) {
        CarAssert.assertStrNotBlank(phone,"手机号不能为空！");
        Integer count = loginInfoMapper.selectCount(new EntityWrapper<LoginInfo>().eq("phone", phone));
        if(count < 1){
            throw new BusinessException(CodeEnum.REGISTER_PHONE_NOT_EXIST);
        }
        String phoneKeyInRedis = BaseConstants.LOGIN_PHONE_CODE_IN_REDIS+phone;
        //发送验证码
        sendSms(phone,phoneKeyInRedis);
    }

    @Override
    public void sendSmsCodeToWechat(Map<String,Object> params) {
        String phone = (String)params.get("phone");
        CarAssert.assertStrNotBlank(phone,CodeEnum.BIND_PHONE_NOT_EMPTY);
        String phoneKeyInRedis = BaseConstants.BIND_PHONE_CODE_IN_REDIS+phone;
        //发送短信验证码
        sendSms(phone,phoneKeyInRedis);
    }
}
